package com.jwaoo.bluetooth;


public class MotionProcess {
    private final  int POS_NUM = 3;
    private final  int MAX_DEPTHS = 10;
    private final  int DIR_UNKNOWN = 0;
    private final  int DIR_DOWN = 1;
    private final  int DIR_UP = 2;
    private final  int DIR_NO = 3;
    private final  int DIR_PREV = 4;
    float[] depths;
    float []display_depths;
    int samples_per_dir;
    int freq;
    int   direction;
    int idle_thrd;
    int depths_num ;
    int found_idle;
    int skip_depths;
    int idleCount;

    public MotionProcess(){
        depths = new float[POS_NUM];
        display_depths = new float[MAX_DEPTHS];
    }

    private int filerNoise(int curDir) {
        if (curDir != direction){
            int noise = 0;
            if (curDir != DIR_NO && direction != DIR_NO){
                if(curDir == DIR_UP){
                    if (depths[POS_NUM-1] + depths[POS_NUM-3] < 1.0){
                        noise = 1;
                        //Log.e(TAG, "noise UP");
                    }
                }else{
                    if (depths[POS_NUM-1] + depths[POS_NUM-3] > 1.0){
                        noise = 1;
                        //Log.e(TAG, "noise Down");
                    }
                }
            }
            if (noise == 0){
                return curDir;
            }else{
                return direction;
            }
        }
        return curDir;
    }

    public void process(float x){
        pushData(x);
        int currDir = updateDirection();
        currDir = mayIdle(x ,currDir);
        if (currDir == DIR_PREV){
            currDir = direction;
        }
        currDir = filerNoise(currDir);
        if (currDir == DIR_NO){
            idleCount ++;
            if (idleCount < 8){
                currDir = direction;
            }
        }else{
            idleCount = 0;
        }

        if (currDir != DIR_NO && direction != DIR_NO){
            samples_per_dir++;
            if (currDir == DIR_UP || currDir == DIR_DOWN){
                if (currDir != direction){
                    samples_per_dir += (POS_NUM-1);
                    freq = samples_per_dir;
                    samples_per_dir = 0;
                }
            }
        }else{
            samples_per_dir = 0;
        }
        direction = currDir;
    }

    public int frequency(){
        if (direction == DIR_NO){
            return 0;
        }else {
            return freq;
        }
    }

    private void pushData(float x){
        for (int i = 0; i < POS_NUM-1; i++)
        {
            depths[i] = depths[i+1];
        }
        depths[POS_NUM-1] = x;
    }

    private int updateDirection()
    {
        if (depths[POS_NUM-1] > depths[POS_NUM-2]  && depths[POS_NUM-2] > depths[POS_NUM-3])
        {
            return DIR_DOWN;
        }
        else if (depths[POS_NUM-1] < depths[POS_NUM-2] && depths[POS_NUM-2] < depths[POS_NUM-3])
        {
            return DIR_UP;
        }
        else if (depths[POS_NUM-1] == depths[POS_NUM-2] && depths[POS_NUM-2] == depths[POS_NUM-3])
        {
            return DIR_NO;
        }
        else {
            return DIR_PREV;
        }
    }


    private int mayIdle(float pos, int cur_dir){
        for (int i = MAX_DEPTHS-2; i >= 0 ; i--)
        {
            display_depths[i+1] = display_depths[i];
        }
        display_depths[0] = pos;

        depths_num++;
        if (depths_num > MAX_DEPTHS){
            depths_num = MAX_DEPTHS;
        }
        if (cur_dir == DIR_NO){
            found_idle = 0;
            skip_depths = 0;
            idle_thrd = 0;
            depths_num = 0;
            return cur_dir;
        }
        if (found_idle != 0){
            skip_depths++;
            //msg_Err(input, "change to idle mode, skip_depths=%d\n", skip_depths);
            if (skip_depths <= 60){
                return DIR_NO;
            }else{
                found_idle = 0;
            }
        }
        for (int i = 1; i < depths_num-1; i++){
            float diff = Math.abs(display_depths[i] - display_depths[0]);
            if (diff < 0.05f){
                //g_Err(input, "diff=%f", diff);
                idle_thrd++;
            }else{
                idle_thrd = 0;
            }
        }
        if (idle_thrd >= 8){
            //Log.e(TAG, "change to idle mode");
            idle_thrd = 0;
            skip_depths = 0;
            found_idle = 1;
            return DIR_NO;
        }
        return cur_dir;
    }


}